#include "mem_block.h"

#ifdef USE_LFS

#ifndef KC1110_2_RTE_RETAIN_LFS_H
#define KC1110_2_RTE_RETAIN_LFS_H

class retain_lfs : public mem_block {
public:
    explicit retain_lfs(const char *fname, const char *fname2 = nullptr) {
        memset(filename, 0, LFS_NAME_MAX * 2);
        strcpy(filename[0], fname);
        strcpy(filename[1], fname2);
    }

    retain_lfs() {
    }

    void begin(const char *name, int write) override {
        memset(filename, 0, LFS_NAME_MAX);
        strcpy(filename[0], name);
        // logger.debug("open_rdonly %s,", filename[0]);
        // md.open_rdonly((const char *) filename[0]);
        // logger.debug("size = %d\n", md.size(name));
        // md.close();
    }

    void Remove(int i) override {
#ifndef LFS_READONLY
        FlashFile::unlink((const char *) filename[i]);
#endif
    }

    static void Remove(const char *name) { FlashFile::unlink(name); }

    int Read(u8 block, unsigned int adr, unsigned int size, void *pVoid) override {
        if (!md.opened()) {
            // logger.debug("open_rdonly %s\n", filename[block]);
            if (md.open_rdonly((const char *) filename[block]) < 0)
                return 0;
        }
        md.fseek(adr, LFS_SEEK_SET);
        int len = md.read((char *) pVoid, size);
        md.close();
        return len;
    }

    void Write(unsigned char block, unsigned int adr, void *pVoid, unsigned int size) override {
#ifndef LFS_READONLY
        if (!md.opened()) {
            // logger.debug("open_write %s\n", filename[block]);
            md.open_write((const char *) filename[block]);
        }
        // logger.debug("write 0x%x,len=%d\n", adr, size);
        md.fseek(adr, LFS_SEEK_SET);
        md.write((const char *) pVoid, size);
#endif
    }

    int Shutdown() override {
        // logger.debug("Shutdown");
        if (md.opened()) {
            md.close();
        }
        return 0;
    };
    int dat_len{}, pos{};

    int begin(byte *file, byte sz, uint32_t data_address, uint32_t data_len) override {
        dat_len = data_len;
        u8 key_len = strlen((const char *) (file));
        if (key_len > sz)
            return -1;
        if (md.opened()) {
            md.close();
        }
#ifndef LFS_READONLY
        md.open_write((const char *) file);
#endif
        return (256 - 16) * 7 / 8;
    };

    int begin_read(byte *file, byte sz, uint32_t start_address, uint32_t data_len) {
        u8 key_len = strlen((const char *) file);
        if (key_len > sz)
            return -1;
        memset(filename[0], 0, LFS_NAME_MAX);
        strcpy(filename[0], (const char *) file);
        if (md.opened()) {
            md.close();
        }
        md.open_rdonly((const char *) file);
        return md.size((const char *) file);
    }

    int Write(byte *pVoid, int size) override {
#ifndef LFS_READONLY
        return md.write((const char *) pVoid, size);
#else
        return -1;
#endif
    };

    const char *name() override { return "lfs"; }

private:
    FlashFile md{};
    char filename[2][LFS_NAME_MAX] = {};
};

#endif // KC1110_2_RTE_RETAIN_LFS_H
#endif
